import type { App, DirectiveBinding } from 'vue';

/**
 * 节流指令
 * @directive 按钮节流指令：v-throttle
 */
interface IElementWithDebounce extends HTMLElement {
	handleClick: () => void;
	throttled: boolean;
	timerId?: ReturnType<typeof setTimeout>;
}

const throttleDirective = (app: App) => {
	app.directive('throttle', {
		mounted(el: IElementWithDebounce, binding: DirectiveBinding) {
			// 传入的不是函数则返回
			if (typeof binding.value !== 'function') return;

			// 判断是否需要立即执行
			const immediate = binding.arg === 'immediate';

			// 获取节流时间
			const wait = Number(import.meta.env.VITE_DELAY) * 2;

			// 记录上一次执行的时间戳
			let lastExecution = 0;

			// 初始化节流状态为未节流
			el.throttled = false;

			el.handleClick = () => {
				const now = Date.now();

				// 检查当前是否处于节流状态，并且距离上一次执行的时间间隔是否超过节流时间
				if (!el.throttled && now - lastExecution >= wait) {
					// 执行绑定的函数
					binding.value();

					// 更新上一次执行的时间戳
					lastExecution = now;

					// 设置节流状态为节流中
					el.throttled = true;

					// 指定事件后重置节流状态
					el.timerId = setTimeout(() => {
						el.throttled = false;
					}, wait);
				}
			};

			el.addEventListener('click', el.handleClick);

			// 立即执行
			if (immediate) binding.value();
		},
		beforeUnmount(el: IElementWithDebounce) {
			el.removeEventListener('click', el.handleClick);
			// 清除定时器
			if (el.timerId) {
				clearTimeout(el.timerId);
				el.timerId = undefined;
			}
		},
	});
};

export default throttleDirective;
